Skip to content

sys/cpu: Use cntvct_el0 instead of cntpct_el0 on aarch64 - #712

Open
hotline1337 wants to merge 1 commit into
Limine-Bootloader:trunkfrom
hotline1337:fix/vct
Open

hotline1337 wants to merge 1 commit into
Limine-Bootloader:trunkfrom
hotline1337:fix/vct

Conversation

@hotline1337

Copy link
Copy Markdown
Contributor

Summary

  • Switched AArch64 timer counter reads from the physical counter (CNTPCT_EL0) to the virtual counter (CNTVCT_EL0) in common/sys/cpu.h and checks/payloads/limine/arch_aarch64.c.
  • Eliminated EL1 trap overhead and synchronous exceptions when booting Limine or running the AArch64 test payload under hypervisors or firmware configurations that restrict physical counter access.

Background & Problem

Per the ARM Architecture Reference Manual for A-profile architecture (ARM DDI 0487), CNTPCT_EL0 reads the physical counter, whereas CNTVCT_EL0 reads the virtual counter, i.e. the physical count minus CNTVOFF_EL2 (treated as zero when EL2 is absent or disabled). Access from lower exception levels may be trapped by the hypervisor.

  1. Hypervisor traps and EL1 access restrictions: Under EL2 hypervisors (such as KVM/QEMU) or firmware environments where CNTHCTL_EL2.EL1PCTEN is cleared, accessing CNTPCT_EL0 from EL1 traps to EL2. Depending on hypervisor configuration, this either incurs costly VM-exit emulation overhead on every timer poll or triggers an unhandled synchronous exception.
  2. Standard EL1 timer interface: CNTVCT_EL0 is intended for EL1/EL0 consumers, executes natively in hardware without trapping to EL2 under standard virtualisation setups, and provides a consistent monotonic counter on both bare metal and virtualised guests.

Changes

  1. common/sys/cpu.h: Updated rdtsc() on AArch64 to read cntvct_el0 instead of cntpct_el0.
  2. checks/payloads/limine/arch_aarch64.c: Updated arch_counter() in the Limine test payload to read cntvct_el0 instead of cntpct_el0.

Verification & Testing

  1. Full Build:
    • Clean compilation under -Werror with 0 warnings and 0 errors.
  2. Test Suite:
    • Executed the AArch64 UEFI test suite in QEMU, confirming that both the bootloader timer routines and the test payload counter read CNTVCT_EL0 cleanly without exceptions.

Firmware or hypervisors with CNTHCTL_EL2.EL1PCTEN cleared trap EL1
reads of CNTPCT_EL0 to EL2, triggering unhandled synchronous exceptions
when no EL2 handler is present. CNTVCT_EL0 avoids this trap.

Signed-off-by: hotline1337 <denuvo at tuta dot io>
@makaroneder

Copy link
Copy Markdown

imagine generating commit message with AI for code replacing cntpct_el0 with cntvct_el0 in 2 lines

@hotline1337

Copy link
Copy Markdown
Contributor Author

imagine generating commit message with AI for code replacing cntpct_el0 with cntvct_el0 in 2 lines

Those 2 lines are literally the difference between a boot failure and a working system on NVIDIA N1X Spark and DGX Spark. Leaving zero context in git blame for why a bootloader swapped CNTPCT_EL0 to CNTVCT_EL0 to bypass CNTHCTL_EL2.EL1PCTEN traps is just lazy

@programmerlexi

Copy link
Copy Markdown
Contributor

@hotline1337 The point @makaroneder was making isn't the fact that there are commit descriptions (which there don't seem to be, i can't see any commit description).

And as you have already noted, context is important, especially for changes like this, please add a commit description. PR descriptions don't show up in the git log.

@hotline1337

Copy link
Copy Markdown
Contributor Author

@hotline1337 The point @makaroneder was making isn't the fact that there are commit descriptions (which there don't seem to be, i can't see any commit description).

And as you have already noted, context is important, especially for changes like this, please add a commit description. PR descriptions don't show up in the git log.

Forgot to force push. Resolved.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants